package old.gui;

import gameAppLayer.MainApp;

import java.util.ArrayList;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;


import utilities.SimpleHashMap;

import com.jme3.app.Application;
import com.jme3.asset.AssetManager;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.system.AppSettings;

/*
 * A particular GUILayout (game GUI screen)
 * A Node that hosts Components (Spatials)
 * Registered with and managed by the GUIStateManager
 */
public abstract class GUILayout extends Node implements ActionListener{

	public GUIViewManager guiManager;
	public MainApp app;
	private float settingRatio;
		
	public int newResX;
	public int newResY;
	public int defaultResX;
	public int defaultResY;
	
	//component that mouse cursor is currently over
	public GUIComponent currComponent; 
	
	//default fallback component, when the mouse is not over any components.  Prevents null checking problems.
	private Geometry defaultGeometry;
	private GUIComponent defaultComponent;
	
	//Links each component to a geometry, enabling reverse lookup
	//(reverse lookup = have component, want to know what geometry its attached to.  JME3 
	//doesn't appear to support this)
	public SimpleHashMap<GUIComponent, Geometry> componentMap = new SimpleHashMap<GUIComponent, Geometry>();
	
	//Listing of all events for this GUI
	public ArrayList<String> events = new ArrayList<String>();	
	
	public GUILayout(MainApp app, String name){
		super(name);
		this.app = app;
		this.guiManager = app.getGUIStateManager();
		settingRatio = (float) guiManager.settings.getWidth()/guiManager.settings.getHeight();
		
		defaultComponent = new Button(1,1);
		defaultGeometry = new Geometry("DEFAULT_BUTTON", defaultComponent);
		defaultGeometry.setLocalTranslation(-1, -1, 0);
		//this.attachChild(defaultGeometry);
		
		currComponent = defaultComponent;
		componentMap.put(defaultComponent, defaultGeometry);
	}
	
	public abstract void initialize();
	//Detach any existing nodes
	//Acquire current aspect ratio
	//Create and attach nodes, geometries, GUIComponent objects at default resolution	
	
	//Register the GUIStateManager to listen for menu-specific events
	public abstract void registerEvents();	
	public abstract void removeEvents();
	
	//register input types this GUIState listens for
	public abstract void registerListeners();
	public abstract void removeListeners();
	
	public void update()
	{
		//check mouse location
		checkCursorPosition();
		
		
	}
	
	public void changeResolution(int newResX, int newResY)
	{
		Node layoutNode;
		Vector3f currPosition;
		Geometry subChild;
		GUIComponent component;
		
		int newX, newY; //new node positions
		int oldWidth, oldHeight, newWidth, newHeight; //old and new GUIComponent sizes
		
		//reset nodes to default resolution positions
		initialize();
		
		//calculate transformations for new resolution
		float transX = (float) newResX/defaultResX;
		float transY = (float) newResY/defaultResY;		
		
		//update Node positions for new resolution
		for (Spatial child: children){
			layoutNode = (Node) child;
			currPosition = layoutNode.getLocalTranslation();
			
			newX = (int) (currPosition.getX()*transX);
			newY = (int) (currPosition.getY()*transY);
			//no change to Z coord.
			
			//update attached component sizes and resolutions
			for (int j = 0; j < layoutNode.getQuantity(); j++)
			{
				subChild = (Geometry) layoutNode.getChild(j);

				//now we have the actual GUIComponent!
				component = (GUIComponent) subChild.getMesh();
				
				oldWidth = component.getComponentWidth();
				oldHeight = component.getComponentHeight();
				
				newWidth = (int) (oldWidth*transX);
				newHeight = (int) (oldHeight*transY);
				
				//update size, resolution of component
				component.resize(newWidth, newHeight);
				//component.setResolution(newResX, newResY);				
			}
		}				
	}
	
	public void checkCursorPosition()
	{				
		if (!testCursorQuick(currComponent))
		{
			currComponent = testCursorFull();			
		}				
	}
	
	//Called when the cursor location is known to be in a particular GUIComponent
	//returns boolean determining if still in that component
	private boolean testCursorQuick(GUIComponent component)
	{
		Geometry geometry = componentMap.get(component);
		
		int cursorX = (int) app.getInputManager().getCursorPosition().x;
		int cursorY = (int) app.getInputManager().getCursorPosition().y;
		
		int compX = 0;
		int compY = 0;
		
		int compWidth = 0;
		int compHeight = 0;		
		
		boolean flag;		
		
		//local translation of geometry
		compX = (int) geometry.getLocalTranslation().getX();
		compY = (int) geometry.getLocalTranslation().getY();
		
		//height, width of component
		compWidth = component.getComponentWidth();
		compHeight = component.getComponentHeight();			

		flag = //the cursor is to the right of the rectangle
			(((compX+compWidth) < cursorX) ||
					//the cursor is to the left of the rectangle
					(compX > cursorX) ||
					//the cursor is above the rectangle
					((compY+compHeight) < cursorY) ||
					//the cursor is below the rectangle
					(compY > cursorY));

		return !flag;
	}
	
	private GUIComponent testCursorFull()
	{
		int size = children.size();
		
		//if (children.size()==0)
		//{return null;}
		
		int cursorX = (int) app.getInputManager().getCursorPosition().x;
		int cursorY = (int) app.getInputManager().getCursorPosition().y;
		
		int compX = 0;
		int compY = 0;
		int compZ = 0;
		
		int compWidth = 0;
		int compHeight = 0;
		
		GUIComponent component;
		GUIComponent finalComponent = defaultComponent;
		int finalComponentZ = 1;
		
		Geometry geometry;
		boolean flag;
		
		for (int i = 0; i < size; i++)
		{
			geometry = (Geometry) children.get(i);
			component = (GUIComponent) geometry.getMesh();
			
			//local translation of geometry
			compX = (int) geometry.getLocalTranslation().getX();
			compY = (int) geometry.getLocalTranslation().getY();
			compZ = (int) geometry.getLocalTranslation().getZ();
			
			//height, width of component
			compWidth = component.getComponentWidth();
			compHeight = component.getComponentHeight();			
			
			flag = //the cursor is to the right of the rectangle
				(((compX+compWidth) < cursorX) ||
						//the cursor is to the left of the rectangle
						(compX > cursorX) ||
						//the cursor is above the rectangle
						((compY+compHeight) < cursorY) ||
						//the cursor is below the rectangle
						(compY > cursorY));
			
			//cursor is within this component and this component is on top of
			//any previously found component.
			if ((!flag) && (compZ < finalComponentZ))
			{
				finalComponent = component;
			}	
		}
		
		if (finalComponent.equals(null))
		{
			finalComponent = defaultComponent;
		}
		
		return finalComponent;
	}
	
}
